/* =========================================================================== *
 * Copyright (c) 2011, Infineon Technologies AG                                *
 * All rights reserved.                                                        *
 *                                                                             *
 * Redistribution and use in source and binary forms, with or without          *
 * modification, are permitted provided that the following conditions are met: *
 * Redistributions of source code must retain the above copyright notice, this *
 * list of conditions and the following disclaimer. Redistributions in binary  *
 * form must reproduce the above copyright notice, this list of conditions and *
 * the following disclaimer in the documentation and/or other materials        *
 * provided with the distribution. Neither the name of the copyright holders   *
 * nor the names of its contributors may be used to endorse or promote         *
 * products derived from this software without specific prior written          *
 * permission.                                                                 *
 *                                                                                                                                                                                                                                                                                                                   *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" *
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,       *
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      *
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR           *
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,       *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,         *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,    *
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR     *
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF      *
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                  *
 * To improve the quality of the software, users are encouraged to share       *
 * modifications, enhancements or bug fixes with                               *
 * Infineon Technologies AG (dave@infineon.com).                               *
 *                                                                             *
 * ========================================================================== */
#include <DAVE3.h>
#include "N25Q032A.h"

/** @brief SPI channel configuration structure */
SPI001_ConfigType TempConfig =
{
 	
		.Mode = 1,/* SPI Mode */
		.HBMode = 1, // Transmit LSB/MSB
	    .ClkPol =  0, // Clock Polarity
		.ClkPh =  1, // Clock Phase
		.BaudRate = 10000000,//Baud Rate
		.LeadTrailDelay =  0,// Leading/TrailingDelay
		.NextFrameDelay = 0,// NextFrameDelay
	    .WordLen = 8,// Wordlength,
		.FrameLen =  63,// Framelength,
		.CESelected =  CE_A,// SlaveSelectline
};

/**
 * @brief This function sends read page command and reads out 256 bytes
 *        of data from sector specified to the given buffer
 *
 * @param Address: Start address of the sector
 * @param pSPIReceiveData: Buffer in which received values are written
 * @return void
 */
void N25Q032A_RD_PAGE(uint32_t Address,  uint16_t  *pSPIReceiveData)
{
   uint16_t tmp, i;
   uint16_t Data = 0;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   TempConfig.FrameLen = 64;
   /* Configure SPI channel with given configuration*/
   SPI001_Configure(&SPI001_Handle0,&TempConfig);
   /* while reading page we are transmitting 256bytes of dummy data in one
    * SPI frame for receiving data. If we specify frame length has 64bit then actual frame length
    * will be indefinite and user needs to control start and end of frame
    *
    * User can control the start and end of frame by calling
    * EnableStartOfFrame() and EnableEndOfFrame() macro  functions*/
   EnableStartOfFrame(SPI001_Handle0);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);

    Data = N25Q032A_CM_READ;
    // Send read page command
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
   //wait for dummy to be received
   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));
   SPI001_ReadData(&SPI001_Handle0,&tmp); 			   // dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     Data = ((Address & 0x00FF0000)>>16);
    // Send 3rd byte of 24bit start address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
   //wait for dummy to be received
  do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0,&tmp);  // dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x0000FF00)>>8);   
    //Send 2nd byte of 24bit start address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
   //wait for dummy to be received
    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));    
   SPI001_ReadData(&SPI001_Handle0,&tmp);     // dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     Data = ((Address & 0x000000FF)>>0);   
     //Send 1st byte of 24bit start address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
   //wait for dummy to be received
   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0,&tmp);     // dummy read

   for (i=0; i<255; i++)			// read 255 bytes from N25Q032A
   {
      SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
      SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
      Data = DUMMY;   
      //Send dummy data to flash chip
      SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
     //wait for data to be received
     do
     {
       Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
       Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));
     // Read data received from flash chip to buffer
     SPI001_ReadData(&SPI001_Handle0,pSPIReceiveData);
     pSPIReceiveData +=1; 
   }
   /* Enable end of frame */
   EnableEndOfFrame(SPI001_Handle0);

 
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = DUMMY;   
    // send 256th dummy data for receiving 256th byte from flash chip
    SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));
   // Read 256th data byte received from flash chip
   SPI001_ReadData(&SPI001_Handle0,pSPIReceiveData);
}        


/**
 *@brief This function sends read status register command to SPI flash chip
 *       and returns Status register value
 *
 * @param[in] None
 * @return	SPI Flash status register value
 *
 */
uint16_t N25Q032A_STATUS_RD()
{
   uint16_t tmp;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 
   uint16_t Data = 0;
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   TempConfig.FrameLen = 16;
   /* Change SPI Channel frame length with above configuration */
   SPI001_Configure(&SPI001_Handle0,&TempConfig);

// Receive first Byte
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);

    Data = N25Q032A_CM_REG_READ_ST;
    // Send the read status register command to SPI flash chip
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
  // Wait till dummy value is received
  do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));

   SPI001_ReadData(&SPI001_Handle0, &tmp); // dummy read

 // Receive second Byte
   // Clear the flags
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = DUMMY;
   //Send dummy data to receive the status register value from flash chip
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
   // Read the status register value
   SPI001_ReadData(&SPI001_Handle0, &tmp);

   return tmp; 						// return the register status 
}


/**
 * @ brief This function read out Configuration register value
 *   of SPI flash chip
 *
 * @param[in] None
 * @return	SPI Flash configuration register value
 *
 */
uint8_t N25Q032A_Configure_RD()
{
   uint16_t tmp;
   uint16_t Data;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   TempConfig.FrameLen = 16;
   SPI001_Configure(&SPI001_Handle0,&TempConfig);


   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = N25Q032A_CM_REG_READ_CFG;
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
   SPI001_ReadData(&SPI001_Handle0, &tmp); 				// dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     Data = DUMMY; 
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0, &tmp);

   return tmp; 						// return the configuration register 
}


/**
 * @brief This function programs 256 bytes of Data to the
 *         sector specified.
 *
 * @param Address: Start address of sector
 * @param pSPISendData: Pointer to buffer where data is available for transmission
 * @return void
 */
void  N25Q032A_Prog_Page(  uint32_t Address,  uint16_t  *pSPISendData)
{
   uint16_t tmp, i;
   uint16_t Data;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   TempConfig.FrameLen = 64;
   /* Configure SPI Channel with above configuration*/
   SPI001_Configure(&SPI001_Handle0,&TempConfig);
   
   /* while programming page we are transmitting 256bytes of data in one
    * SPI frame. If we specify frame length has 64bit then actual frame length
    * will be indefinite and user needs to control start and end of frame
    *
    * User can control the frame by calling
    * EnableStartOfFrame() and EnableEndOfFrame() macro  functions*/

   // Enable start of frame
   EnableStartOfFrame(SPI001_Handle0);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   /* Write program page data */
    Data = N25Q032A_CM_PROG_PAGE;
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

  do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
   SPI001_ReadData(&SPI001_Handle0, &tmp); 				// dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x00FF0000)>>16);  
    /*Send 3rd byte of 24bit address of sector*/
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
   SPI001_ReadData(&SPI001_Handle0,&tmp);// dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x0000FF00)>>8);   
    /*Send 2nd byte of 24bit address of sector*/
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));  
   SPI001_ReadData(&SPI001_Handle0,&tmp);

      SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x000000FF)>>0);  
    /*Send 1st byte of 24bit address of sector*/
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
   SPI001_ReadData(&SPI001_Handle0,&tmp);

   /* Start sending 255 bytes of data from buffer */
   for (i=0; i<255; i++)
   {
     SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
     SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     SPI001_WriteData(&SPI001_Handle0, pSPISendData,SPI001_STANDARD);

      do
       {
         Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
         Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
      }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));     
     SPI001_ReadData(&SPI001_Handle0,&tmp);       // dummy read
     pSPISendData++; 
   }
   /* Enable end of frame */
    EnableEndOfFrame(SPI001_Handle0);
    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     /* Send the 256th byte
      * After sending this data, frame will be finished since we
      * enable end of frame*/
    SPI001_WriteData(&SPI001_Handle0, pSPISendData,SPI001_STANDARD);

     do
    {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
     }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
    SPI001_ReadData(&SPI001_Handle0, &tmp);   // dummy read
}


/**
 * @brief This function sends sector erase command
 *
 * @Param[in]: Address: Start address of the sector
 * @return : void
 */
void  N25Q032A_Sector_Erase(  uint32_t Address)
{
  uint16_t tmp;
  uint16_t Data;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   TempConfig.FrameLen = 32;
   /* Configure SPI Channel with above configuration */
   SPI001_Configure(&SPI001_Handle0,&TempConfig);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = N25Q032A_CM_ERASE_SE;
   /* Send Sector Erase command */
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
   //Wait for dummy value to be received
   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
  // Dummy read
  SPI001_ReadData(&SPI001_Handle0, &tmp);

  SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
  SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
  Data = ((Address & 0x00FF0000)>>16); 
  /*Send 24 bit address of sector starting from MSB
   * Send 3rd byte of 24bit address*/
  SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

  do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
  SPI001_ReadData(&SPI001_Handle0, &tmp);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   /*Send 24 bit address of sector starting from MSB
    * Send 2nd byte of 24bit address*/
   Data = ((Address & 0x0000FF00)>>8);   
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
  SPI001_ReadData(&SPI001_Handle0, &tmp);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data =((Address & 0x000000FF)>>0);   
    /*Send 24 bit address of sector starting from MSB
     * Send 1st byte of 24bit address*/
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

  do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET))); 
  SPI001_ReadData(&SPI001_Handle0, &tmp);
}


/**
 * @brief This function sends the write enable command to SPI flash chip
 *
 * @param[in]: None
 * @return : void
 */
void N25Q032A_WriteEnable()
{
   uint16_t tmp;
   uint16_t Data = 0;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 

   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   /*Chanbe the frame length to 8 for sending
    * Write Enable command to flash chip*/
   TempConfig.FrameLen = 8;
   /* Configure the SPI Channel */
   SPI001_Configure(&SPI001_Handle0,&TempConfig);
   /* clear Standard receive indication and Alternative receive indication flag */
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);

   Data = N25Q032A_CM_WRITE_EN;
   /* Send Write Enable Command */
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
   /* Wait till dummy data is received from flash chip */
    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));
    /* Do a dummy read*/
   SPI001_ReadData(&SPI001_Handle0,&tmp);
}

/*
 * This function writes the given value to status and configuration
 * register of SPI flash chip
 *
 * @param[in] StatusValue: Value for status register
 * @param[in] ConfigureValue: Value for configuration register
 * @return : void
 *
 *
 * */
void N25Q032A_WriteConfigRegister(uint8_t ConfigureValue)
{
   uint16_t tmp;
   uint16_t Data;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0; 
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;
   TempConfig.FrameLen = 16;
   // Configure SPI channel with given configuration
   SPI001_Configure(&SPI001_Handle0,&TempConfig);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);

    Data = N25Q032A_CM_REG_WRITE_CFG;
    //Send status register write data
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));  
   SPI001_ReadData(&SPI001_Handle0,&tmp); 				// dummy read
  
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ConfigureValue;
    // Write the value of status register
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));  
   SPI001_ReadData(&SPI001_Handle0,&tmp);   // dummy read
}

/**
 * @brief This function reads 256bytes of data from the given sector to
 *         the buffer provided
 *
 * @param[in]: Address Start address of sector
 * @param[in]: pSPIReceiveData Buffer pointer
 * @return : void
 * */
void N25Q032A_QuadRD_PAGE(  uint32_t Address,  uint16_t  *pSPIReceiveData)
{
   uint16_t tmp, i;
   uint16_t Data = 0;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0;
   TempConfig.Mode = SPI001_QUAD;
   TempConfig.FrameLen = 64;
   /* Configure the Pin in Quad Mode */
   DAVE_MUX_Init();
   //Configure the channel with given configuration
   SPI001_Configure(&SPI001_Handle0,&TempConfig);

   /* while reading page we are transmitting 256bytes of dummy data in one
    * SPI frame for receiving data. If we specify frame length has 64bit then actual frame length
    * will be indefinite and user needs to control start and end of frame
    *
    * User can control the start and end of frame by calling
    * EnableStartOfFrame() and EnableEndOfFrame() macro  functions*/
   EnableStartOfFrame(SPI001_Handle0);

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = N25Q032A_CM_QUAD_READ;
    // Send quad read command
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0,&tmp); 				// dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x00FF0000)>>16);
    // Send 3rd byte of 24 bit address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));      
   SPI001_ReadData(&SPI001_Handle0,&tmp);

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   // Send 2nd byte of 24 bit address
    Data = ((Address & 0x0000FF00)>>8); 
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);
   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));     
   SPI001_ReadData(&SPI001_Handle0,&tmp);

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x000000FF)>>0);  
    // Send 1st byte of 24 bit address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));      
   SPI001_ReadData(&SPI001_Handle0, &tmp);
  
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = DUMMY;
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));      
   SPI001_ReadData(&SPI001_Handle0, &tmp);

    __NOP(); /* here a timeout need to be added */		
    __NOP(); 
   // Send 255 Dummy data to receive data from SPI Flash
   for (i=0; i<255; i++)
   {
      SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
      SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
      Data = DUMMY; 
     SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_QUADMODE_HPC_INPUTMODE); 

     do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));     
     SPI001_ReadData(&SPI001_Handle0, pSPIReceiveData);
     pSPIReceiveData +=1; 

  }
   /* Enable End of frame */
   EnableEndOfFrame(SPI001_Handle0);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = DUMMY;
   //Send 256 dummy data to receive 256th byte
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_QUADMODE_HPC_INPUTMODE);   

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0, pSPIReceiveData);

}


/*
 * @brief This function writes 256bytes of Data from given buffer to the
 *        sector starting from 0x00000000
 *
 * @param[in] Address Start address of sector
 * @param[in] pSPISendData pointer to data buffer
 * @return: None
 * */
void N25Q032A_QuadWrite_PAGE(  uint32_t Address,  uint16_t  *pSPISendData)
{
   uint16_t tmp, i;
   uint16_t Data = 0;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0;
   TempConfig.FrameLen = 64;
   TempConfig.Mode = SPI001_QUAD;
   /* Configure the Pin in Quad Mode */
   DAVE_MUX_Init();
   // Configure SPI Channel
   SPI001_Configure(&SPI001_Handle0,&TempConfig);
   /* while programming page we are transmitting 256bytes of data in one
    * SPI frame. If we specify frame length has 64bit then actual frame length
    * will be indefinite and user needs to control start and end of frame
    *
    * User can control the frame by calling
    * EnableStartOfFrame() and EnableEndOfFrame() macro  functions*/
   EnableStartOfFrame(SPI001_Handle0);
   // Clear the flags
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = N25Q032A_CM_PROG_QPAGE;
   // Send command for Quad program page
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));    
   SPI001_ReadData(&SPI001_Handle0,&tmp); // dummy read

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x00FF0000)>>16);  
    // Send 3rd byte of 24 bit address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));  
   SPI001_ReadData(&SPI001_Handle0,&tmp);

    SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    Data = ((Address & 0x0000FF00)>>8);
    // Send 2nd byte of 24 bit address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0,&tmp);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = ((Address & 0x000000FF)>>0);
   // Send 1st byte of 24 bit address
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD_HPC_OUTPUTMODE);

  do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));    
   SPI001_ReadData(&SPI001_Handle0,&tmp);
 // Send 255 bytes of Data
  for (i=0; i<255; i++)
  {
     SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
     SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
    SPI001_WriteData(&SPI001_Handle0,pSPISendData,SPI001_QUADMODE_HPC_OUTPUTMODE);

    do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
    SPI001_ReadData(&SPI001_Handle0,&tmp);
    pSPISendData++; 
  }
  // Enable end of frame
   EnableEndOfFrame(SPI001_Handle0);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   // Send 256th byte. After this frame will be finished
   SPI001_WriteData(&SPI001_Handle0,pSPISendData,SPI001_QUADMODE_HPC_OUTPUTMODE);
   do
   {
    Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));   
   SPI001_ReadData(&SPI001_Handle0,&tmp);

}

void N25Q032A_RDID(uint16_t  *pSPIReceiveData)
{
   uint16_t tmp, i;
   uint16_t Data = 0;
   uint8_t Status1 = 0;
   uint8_t Status2 = 0;

   TempConfig.FrameLen = 64;
   TempConfig.Mode = SPI001_STANDARD_FULLDUPLEX;

   /* Configure SPI channel with given configuration*/
   SPI001_Configure(&SPI001_Handle0,&TempConfig);

   /* while reading page we are transmitting 69bytes of dummy data in one
    * SPI frame for receiving data. If we specify frame length has 64bit then actual frame length
    * will be indefinite and user needs to control start and end of frame
    *
    * User can control the start and end of frame by calling
    * EnableStartOfFrame() and EnableEndOfFrame() macro  functions
    * */
   EnableStartOfFrame(SPI001_Handle0);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);

   Data = 0x9F; //RDID
   /* Send read page command */
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   /*wait for dummy to be received*/
   do
   {
	   Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
	   Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));

   SPI001_ReadData(&SPI001_Handle0,&tmp);	// dummy read

   for (i=0; i<69; i++)	// read 69 bytes from N25Q032A
   {
      SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
      SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
      Data = DUMMY;

      /* Send dummy data to flash chip */
      SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);
      /* wait for data to be received */
      do
      {
    	  Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
    	  Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
      }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));

      /* Read data received from flash chip to buffer */
      SPI001_ReadData(&SPI001_Handle0,pSPIReceiveData);
      pSPIReceiveData +=1;
   }

   /* Enable end of frame */
   EnableEndOfFrame(SPI001_Handle0);

   SPI001_ClearFlag(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
   SPI001_ClearFlag(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   Data = DUMMY;

   /* send 69th dummy data for receiving 256th byte from flash chip */
   SPI001_WriteData(&SPI001_Handle0,&Data,SPI001_STANDARD);

   do
   {
	   Status1 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_RECV_IND_FLAG);
	   Status2 = SPI001_GetFlagStatus(&SPI001_Handle0,SPI001_ALT_RECV_IND_FLAG);
   }while(!((Status1 == SPI001_SET) || (Status2 == SPI001_SET)));

   /* Read 69th data byte received from flash chip */
   SPI001_ReadData(&SPI001_Handle0,pSPIReceiveData);
}

void N25Q032A_Std_Config()
{
	N25Q032A_WriteEnable();
	N25Q032A_WriteConfigRegister(N25Q032A_CM_STD_CFG_VALUE);
}
